﻿using System;
using RayDen.Library.Core.Primitives;
using RayDen.RayEngine.Core.Types;
using RayDen.RayEngine.Data;

namespace RayDen.MegaRay.Imaging
{
    public class SampleBufferBase<TPixel>
        where TPixel : IRgbConvertible
    {
        private SampleBufferElement<TPixel>[] samples;
        private int currentFreeSample;


        //public int NonBlackSamples { get { return samples.Count(item => !item.Radiance.IsBlack()); }}

        public SampleBufferBase(int size)
        {
            samples = new SampleBufferElement<TPixel>[size];
            Reset();
        }


        public SampleBufferElement<TPixel>[] Samples
        {
            get
            {
                return samples;
            }
        }

        public void SplatSample(Sample sample, ref TPixel rad, float pw = 1.0f)
        {
#if DEBUG
            //rad.AssertNaN();
#endif
            //try{
            currentFreeSample++;
            if (currentFreeSample >= samples.Length)
                return;
            if (currentFreeSample < 0)
                return;
            samples[currentFreeSample] = new SampleBufferElement<TPixel>()
                {
                    Pass = sample.pass,
                    Weight = pw,
                    Radiance = rad,
                    X = sample.imageX,
                    Y = sample.imageY
                };
            /*}catch (Exception ex)

            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(currentFreeSample);
            }*/

            //samples[currentFreeSample].screenX = sample.imageX;
            //samples[currentFreeSample].screenY = sample.imageY;
            //samples[currentFreeSample].pass = sample.pass;
            //samples[currentFreeSample].PathWeight = pw;

#if SPECTRUM

            samples[currentFreeSample].radiance = new RgbSpectrum(rad.XYZ());
#else
            //samples[currentFreeSample].radiance = rad;

#endif
        }

        public void SplatSample(float imageX, float imageY, ref TPixel rad, float pw = 1.0f, int weight = 1)
        {
            currentFreeSample++;
            if (currentFreeSample >= samples.Length)
            {
                this.currentFreeSample = samples.Length + 1;
                return;
            }
            samples[currentFreeSample].X = imageX;
            samples[currentFreeSample].Y = imageY;
            samples[currentFreeSample].Pass += weight > 0 ? weight : 1;
            samples[currentFreeSample].Weight = pw;
            samples[currentFreeSample].Radiance = rad;
        }

        public bool IsFull()
        {
            return (currentFreeSample >= samples.Length);
        }

        public void WriteMax()
        {
            // Console.WriteLine("Max radiance {0}", this.samples.Max(p=>p.radiance));
        }
        public int GetSampleCount()
        {
            return Math.Min(currentFreeSample, samples.Length - 1);
        }

        public void Reset()
        {
            var ln = samples.Length;
            //Array.ForEach(samples, item => new SampleBufferElem());
            samples = new SampleBufferElement<TPixel>[ln];
            currentFreeSample = 0;
        }
    }
}